﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CPF_experement
{
    class Point
    {
        protected int x;
        protected int y;
        protected int time;
        public int direction;

        public Point(int x, int y,int direction)
        {
            this.x = x;
            this.y = y;
            this.direction = direction;
            this.time = 0;
        }
        public Point(int x, int y, int direction,int time)
        {
            this.x = x;
            this.y = y;
            this.direction = direction;
            this.time = time;
        }
        public Point(Point cpy)
        {
            this.x = cpy.x;
            this.y = cpy.y;
            this.time = cpy.time;
            this.direction = cpy.direction;
        }
        public Point getColaidingPoint()
        {
            switch (direction)
            {
                case 1:
                    return new Point(this.x + 1 ,this.y , 3,this.time);
                case 2:
                    return new Point(this.x, this.y - 1, 4, this.time);
                case 3:
                    return new Point(this.x - 1, this.y, 1, this.time);
                case 4:
                    return new Point(this.x, this.y + 1, 2, this.time);
                case 5:
                    return new Point(this.x + 1, this.y - 1, 7, this.time);
                case 6:
                    return new Point(this.x - 1, this.y - 1, 8, this.time);
                case 7:
                    return new Point(this.x - 1, this.y + 1, 5, this.time);
                case 8:
                    return new Point(this.x + 1, this.y + 1, 6, this.time);
            }
            return this;
        }
        public bool isColaiding(Point other)
        {
            if (this.time != other.time)
                return false;
            if (this.x == other.x && this.y == other.y)
                return true;
            switch (direction)
            {
                case 0:
                    return false;
                case 1:
                    return (other.x == this.x + 1 && other.y == this.y && other.direction == 3);
                case 2:
                    return (other.x == this.x && other.y == this.y-1 && other.direction == 4);
                case 3:
                    return (other.x == this.x - 1 && other.y == this.y && other.direction == 1);
                case 4:
                    return (other.x == this.x && other.y == this.y+1 && other.direction == 2);
                case 5:
                    return (other.x == this.x + 1 && other.y == this.y-1 && other.direction == 7);
                case 6:
                    return (other.x == this.x - 1 && other.y == this.y-1 && other.direction == 8);
                case 7:
                    return (other.x == this.x - 1 && other.y == this.y+1 && other.direction == 5);
                case 8:
                    return (other.x == this.x + 1 && other.y == this.y+1 && other.direction == 6);
            }
            return false;
        }
        public override int GetHashCode()
        {
            return (x + 1) * (y + 1);
        }
        public override bool Equals(object obj)
        {
            Point that = (Point)obj;
            return (this.time == that.time && this.x == that.x && this.y == that.y && (this.direction == that.direction || this.direction==-1 || that.direction==-1));
        }
    }
    class PoinForNewAlgoritem : Point
    {
        public PoinForNewAlgoritem(int to_x, int to_y, int direction, int time)
            : base(to_x, to_y, direction, time)
        { }

        public PoinForNewAlgoritem copyPointNoDirection()
        {
            return new PoinForNewAlgoritem(base.x, base.y, -1, base.time);
        }
        public PoinForNewAlgoritem parkedAgent()
        {
            return new PoinForNewAlgoritem(base.x, base.y, -1, base.time + 1);
        }

        public static int getDirection(int to_x, int to_y, int from_x, int from_y)
        {
            int temp = 0;
            temp += (to_x - from_x);
            temp += (to_y - from_y) * 2;
            switch (temp)
            {
                case 0:
                    return 0;
                case -1:
                    return 1;
                case 2:
                    return 2;
                case 1:
                    return 3;
                case -2:
                    return 4;
            }
            return 0;
        }
        public override int GetHashCode()
        {
            return base.x * base.y * base.time;
        }
        public PoinForNewAlgoritem getColaidingPoint()
        {
            switch (direction)
            {
                case 1:
                    return new PoinForNewAlgoritem(this.x + 1, this.y, 3, this.time);
                case 2:
                    return new PoinForNewAlgoritem(this.x, this.y - 1, 4, this.time);
                case 3:
                    return new PoinForNewAlgoritem(this.x - 1, this.y, 1, this.time);
                case 4:
                    return new PoinForNewAlgoritem(this.x, this.y + 1, 2, this.time);
                case 5:
                    return new PoinForNewAlgoritem(this.x + 1, this.y - 1, 7, this.time);
                case 6:
                    return new PoinForNewAlgoritem(this.x - 1, this.y - 1, 8, this.time);
                case 7:
                    return new PoinForNewAlgoritem(this.x - 1, this.y + 1, 5, this.time);
                case 8:
                    return new PoinForNewAlgoritem(this.x + 1, this.y + 1, 6, this.time);
            }
            return this;
        }
        public override string ToString()
        {
            return "step - "+base.time+" posision - ("+base.x+","+base.y+")";
        }
    }
}
